#include <iostream>
#include <unistd.h>
#include <semaphore.h>
#include <pthread.h>
using namespace std;

#define BUFFER_SIZE 5

typedef struct CircularQueue
{
    int buffer[BUFFER_SIZE];
    int head;
    int tail;
} CQ;

CQ queue;
sem_t Empty; // 剩余空间数量
sem_t Full;
sem_t Mutex;
int Data = 1;

void Init_Queue()
{
    queue.head = 0;
    queue.tail = 0;

    sem_init(&Empty, 0, BUFFER_SIZE);
    sem_init(&Full, 0, 0);
    sem_init(&Mutex, 0, 1);
}

void* producer(void* arg)
{
    while (1)
    {
        sem_wait(&Empty);
        sem_wait(&Mutex);
        queue.buffer[queue.tail++] = Data;
        queue.tail %= BUFFER_SIZE;
        cout << "producer: " << Data++ << endl;
        sem_post(&Full);
        sem_post(&Mutex);
    }
}

void* consumer(void* arg)
{
    while (1)
    {
        sem_wait(&Full);
        sem_wait(&Mutex);
        int t = queue.buffer[queue.head++];
        queue.head %= BUFFER_SIZE;
        cout << "consumer: " << t << endl;
        sem_post(&Empty);
        sem_post(&Mutex);
        sleep(1);
    }
}

int main()
{
    Init_Queue();

    pthread_t producer_thread, consumer_thread;
    pthread_create(&producer_thread, nullptr, producer, nullptr);
    pthread_create(&consumer_thread, nullptr, consumer, nullptr);

    pthread_join(producer_thread, nullptr);
    pthread_join(consumer_thread, nullptr);

    return 0;
}